package com.yc.common.utils.ip;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yc.common.utils.spring.SpringUtil;
import com.yc.common.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * IP地址位置工具类
 */
@Component
public class AddressUtil {
    private static final Logger logger = LoggerFactory.getLogger(AddressUtil.class);

    // IP地址查询API
    private static final String IP_URL = "https://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true";

    /**
     * 获取IP地址的地理位置
     *
     * @param ip IP地址
     * @return 地理位置，格式：国家-省份-城市：详细地址
     */
    public static String getRealAddressByIP(String ip) {
        // 检查是否为本地IP
        if (StringUtil.isEmpty(ip) || "127.0.0.1".equals(ip) || "localhost".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
            return "本地-开发环境：本机访问";
        }

        // 检查是否为内网IP
        if (isInternalIp(ip)) {
            // 获取本机IP，判断是否为虚拟机访问
            String localIp = IpUtil.getLocalIpv4Address();
            if (ip.equals(localIp)) {
                return "本地-虚拟环境：虚拟机访问(" + ip + ")";
            }
            return "内网-局域网：局域网访问(" + ip + ")";
        }

        try {
            String url = String.format(IP_URL, ip);
            RestTemplate restTemplate = SpringUtil.getBean(RestTemplate.class);
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                String json = response.getBody();
                JSONObject obj = JSON.parseObject(json);
                logger.info("IP地址查询结果: {}", json);

                // 获取省份和城市信息
                String province = obj.getString("pro");
                String city = obj.getString("city");
                String addr = obj.getString("addr");

                // 构建地理位置字符串
                StringBuilder location = new StringBuilder("中国");

                // 添加省份
                if (province != null && !province.isEmpty()) {
                    location.append("-").append(province);
                }

                // 添加城市（如果城市不为空且不等于省份）
                if (city != null && !city.isEmpty() && !city.equals(province)) {
                    location.append("-").append(city);
                }

                // 添加详细地址（如果有）
                if (addr != null && !addr.isEmpty()) {
                    // 将地址保存到日志中
                    return location.toString() + "：" + addr.trim();
                }

                return location.toString();
            }
        } catch (Exception e) {
            logger.error("获取IP地址位置信息失败: {}", e.getMessage());
        }

        return "未知位置：无法获取地理信息(" + ip + ")";
    }

    /**
     * 判断是否为内网IP
     *
     * @param ip IP地址
     * @return 是否为内网IP
     */
    public static boolean isInternalIp(String ip) {
        if (ip == null || ip.isEmpty()) {
            return true;
        }

        // 判断是否为内网IP
        byte[] addr = textToNumericFormatV4(ip);
        if (addr == null) {
            return false;
        }

        return isInternalIp(addr);
    }

    /**
     * 将IPv4地址转换成字节数组
     *
     * @param text IPv4地址
     * @return 字节数组
     */
    public static byte[] textToNumericFormatV4(String text) {
        if (text.length() == 0) {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try {
            if (elements.length == 4) {
                for (int i = 0; i < elements.length; i++) {
                    int value = Integer.parseInt(elements[i]);
                    if (value < 0 || value > 255) {
                        return null;
                    }
                    bytes[i] = (byte) value;
                }
            } else {
                return null;
            }
        } catch (NumberFormatException e) {
            return null;
        }

        return bytes;
    }

    /**
     * 判断是否为内网IP
     *
     * @param addr IP地址字节数组
     * @return 是否为内网IP
     */
    private static boolean isInternalIp(byte[] addr) {
        final byte b0 = addr[0];
        final byte b1 = addr[1];

        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;

        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                if (b1 == SECTION_6) {
                    return true;
                }
            default:
                return false;
        }
    }
}